package com.si.anddos.library.provider.rapidshare;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import android.util.Log;
import com.si.anddos.dpadapters.Account;
import com.si.anddos.library.main.AccountDetail;
import com.si.anddos.library.provider.FileInfo;
import com.si.anddos.library.provider.ServiceProvider;
import com.si.anddos.library.provider.ServiceProviderException;
import com.si.anddos.library.provider.ServiceProviderListener;
import com.si.anddos.utils.FileSaver;
import com.si.anddos.utils.Utils;

public class RapidshareUploadProvider implements ServiceProvider {

	private ServiceProviderListener listener;
	// private Thread t;
	private File file;
	private String user;
	private String pass;
	private String boundary = "----------" + Utils.getDateLong();
	private int accountType = 0;

	// Information about uploading;
	private long uploadedSize = 0;

	// Uploaded data information
	private String fileURL = "0";
	private String fileKillURL = "0";
	private int chunkSize = 1000000;
	private int fileID = 0;
	private int killCode = 0;

	private int serverN = 0;

	public synchronized String getFileKillURL() {
		return fileKillURL;
	}

	public synchronized String getFileURL() {
		return fileURL;
	}

	public synchronized long getUploadedSize() {
		return uploadedSize;
	}

	public void setServiceProviderListener(ServiceProviderListener listener) {

		this.listener = listener;

	}

	public void setFileSaver(FileSaver fileSaver) {
		// TODO Auto-generated method stub

	}

	public URL getURL() {
		// TODO Auto-generated method stub
		return null;
	}

	public FileInfo getFileInfo(URL url) {
		// TODO Auto-generated method stub
		return null;
	}

	public AccountDetail getAccountDetail(Account account)
			throws ServiceProviderException {
		// TODO Auto-generated method stub
		return null;
	}

	public void download(long position) {
		// TODO Auto-generated method stub

	}

	public void download(Account account, long position) {
		// TODO Auto-generated method stub

	}

	public void upload(File file) {
		this.file = file;
		this.user = "";
		this.pass = "";
		run();

	}

	public void upload(File file, String userName, String password) {
		this.file = file;
		this.user = userName;
		this.pass = password;
		this.accountType = 1;
		run();

	}

	// this function is called
	public void upload(File file, Account accont) {
		this.file = file;
		this.pass = accont.getPassword();
		this.user = accont.getUserName();
		System.out.println("Volani funkce upload s Account parametry user: "
				+ this.user + " , pass: " + this.pass);
		// this.user = "anddosTest";
		// this.pass = "rapidapi00";
		// System.out.println("Volani funkce upload s parametry user: " + user +
		// " , pass: " + pass);
		run();
	}

	public void stopDownload() {
		// TODO Auto-generated method stub

	}

	public void pause(boolean isLogged) {
		// TODO Auto-generated method stub

	}

	public void run() {

		if (listener != null) {
			listener.uploadStart(this);
		}

		System.out.println("Spusteno vlakno");
		if (file.exists() && file.canRead()) {
			System.out.println("Soubor existuje a lze ho cist." + file.length()
					+ " Boundary: " + boundary);
			try {
				// System.out.println("Moje MD5: " + Utils.getMD5(file));
				int serverNumber = getNextUploadServer();
				serverN = serverNumber;
				boolean resumed = false;
				// System.out.println("Toto je odpoved: " + serverNumber);
				if (fileID > 0 || killCode > 0) {
					// uploadedSize = checkIncomplete(String.valueOf(fileID),
					// String.valueOf(killCode));
					uploadedSize = checkIncomplete(fileURL, fileKillURL);
				}
				if (uploadedSize == -1) {
					uploadedSize = 0;
				}
				boolean chunks = false;
				boolean complete = false;
				int actualChunkSize = 0;
				while (uploadedSize < file.length()) {

					uploadedSize = checkIncomplete(fileURL, fileKillURL);
					if (uploadedSize == -1) {
						uploadedSize = 0;
					}
					// --------------------------------
					if (file.length() > chunkSize) {
						System.out.println("Soubor je vetsi nez chunk.");
						chunks = true;
						actualChunkSize = (int) (file.length() - uploadedSize);
						if (actualChunkSize > chunkSize)
							actualChunkSize = chunkSize;
						else
							complete = true;
					} else {
						System.out.println("Soubor je mensi nez chunk.");
						chunks = false;
						actualChunkSize = (int) (file.length());
					}
					uploadData(chunks, resumed, complete, uploadedSize,
							actualChunkSize);
					resumed = true;
				}

			} catch (IOException ex) {
				Log.i("RapidshareUploadProvider", "IOException soubor / SERVER");
			}

		} else {
			System.out.println("Soubor neexistuje.");
		}
	}

	private void setURLParameters(URLConnection htc, long totalSize) {
		htc.setRequestProperty("Content-Type", "multipart/form-data; boundary="
				+ boundary);
		System.out.println("Velikost: " + totalSize);
		htc.setRequestProperty("Content-Length", String.valueOf(totalSize));
		htc.setRequestProperty("Content-Disposition",
				"form-data; name=\"rsapi_v1\"");
		htc.addRequestProperty("Accept-Encoding", "identity");
		htc.addRequestProperty("UserAgent", "RapidUploader[v1,2]");
		/*
		 * htc.addRequestProperty("Referer", "http://rapidshare.com/");
		 * htc.addRequestProperty("UserAgent", "RapidUploader[v1,2]");
		 * htc.addRequestProperty("Accept-Charset",
		 * "iSO-8859-1,utf-8;q=0.7,*;q=0.7");
		 * htc.addRequestProperty("Accept-Encoding", "identity");
		 * htc.addRequestProperty("Accept-Language", "de-de;q=0.5,en;q=0.3");
		 */

	}

	private void uploadData(boolean chunks, boolean resumed, boolean complete,
			long start, int nbyte) {
		try {
			String contentTail = "\r\n" + boundary + "--\r\n";
			byte[] contentTailSize;
			String contentHeader = getContentHeader(boundary, file.getName(),
					user, pass, 1, chunks, resumed, complete);
			byte[] contetntHeaderByte;

			contentTailSize = contentTail.getBytes("UTF-8");
			contetntHeaderByte = contentHeader.getBytes("UTF-8");
			long totalSize = nbyte + contentTailSize.length
					+ contentHeader.length();

			URL uploadUrl;

			if (resumed)
				uploadUrl = new URL("http://rs" + serverN
						+ ".rapidshare.com/cgi-bin/uploadresume.cgi");
			else
				uploadUrl = new URL("http://rs" + serverN
						+ ".rapidshare.com/cgi-bin/upload.cgi");
			HttpURLConnection htc = (HttpURLConnection) uploadUrl
					.openConnection();
			setURLParameters(htc, totalSize);
			htc.setRequestMethod("POST");
			htc.setDoOutput(true);
			htc.setUseCaches(false);
			htc.connect();

			OutputStream os = htc.getOutputStream();
			// -----------------------------------------------------------------------
			os.write(contetntHeaderByte);
			// System.out.println("Posila pozadavek POST! serverNumber" +
			// serverNumber + "------------------------------------------");
			System.out.println(contentHeader);

			sendFile(os, start, nbyte);
			System.out
					.println("Posila SOUBOR.-------------------------------------------------------------");
			os.write(contentTailSize);
			String response = Utils.inputStreamAsString(htc.getInputStream());
			System.out.println("Odpoved na pozadavek " + response);
			if (resumed) {
				;
			} else {
				System.out.println(checkUpload(response));
			}

			os.flush();
			os.close();

			if (fileKillURL != null && fileURL != null) {
				System.out.println(checkIncomplete(fileURL, fileKillURL));
			}
		} catch (UnsupportedEncodingException ex) {
			Log.i("RapidshareUploadProvider", "UnsupportedEncodingException");
		} catch (IOException ex) {
			Log.i("RapidshareUploadProvider", "IOException Server not found");
		}
	}

	private int getNextUploadServer() throws UnsupportedEncodingException,
			IOException {
		int serverNumber = -1;
		URL nextServerUrl = new URL(
				"http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=nextuploadserver_v1");
		URLConnection connection = nextServerUrl.openConnection();
		InputStream responseStream = connection.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(
				responseStream, "UTF-8"));
		String response = br.readLine();
		serverNumber = Integer.parseInt(response);
		if (responseStream != null) {
			responseStream.close();
		}
		return serverNumber;
	}

	private int checkIncomplete(String pfileid, String pkillcode)
			throws UnsupportedEncodingException, IOException {
		URL nextServerUrl = new URL(
				"http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkincomplete_v1&fileid="
						+ pfileid + "&killcode=" + pkillcode);
		URLConnection connection = nextServerUrl.openConnection();
		InputStream responseStream = connection.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(
				responseStream, "UTF-8"));
		String response = br.readLine();
		if (responseStream != null) {
			responseStream.close();
		}
		System.out.println("Funkce check incomplete: " + response);
		if (response != null && response.length() > 5) {
			response.toLowerCase();
			String ps = response.substring(0, 5);
			if (ps.equalsIgnoreCase("error")) {
				return -1;
			}
			// int posledniIndex = response.s
			// ps = response.substring(0, response.indexOf(' '));
			// return Integer.parseInt(ps);
			return Integer.parseInt(response);
		}
		return -1;
	}

	private String getContentHeader(String boundary, String FName,
			String username, String password, int AccountType, boolean chunks,
			boolean resumed, boolean complete) {
		StringBuilder sb = new StringBuilder();
		// first boundary
		sb.append(boundary);
		sb.append("\r\nContent-Disposition: form-data; name=\"rsapi_v1\"\r\n\r\n1\r\n");
		sb.append(boundary);
		sb.append("\r\n");

		if (resumed) {
			// System.out.println("Navrat k predchozimu uploadu!!!!!!!!!!!!!");
			sb.append("Content-Disposition: form-data; name=\"fileid\"\r\n\r\n"
					+ fileURL + "\r\n");
			sb.append(boundary
					+ "\r\nContent-Disposition: form-data; name=\"killcode\"\r\n\r\n"
					+ fileKillURL + "\r\n");
			if (complete)
				sb.append(boundary
						+ "\r\nContent-Disposition: form-data; name=\"complete\"\r\n\r\n1\r\n");
		} else {
			// System.out.println("Uplne novy upload");
			if (AccountType != 0) { // Free User
				if (AccountType == 1) { // Premium Account
					sb.append("Content-Disposition: form-data; name=\"login\"");
				} else {// Collector Account
					sb.append("Content-Disposition: form-data; name=\"freeaccountid\"");
				}
				sb.append("\r\n\r\n" + username + "\r\n");
				sb.append(boundary);
				sb.append("\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n"
						+ password + "\r\n");
			}// else if Free User
			if (chunks) {
				sb.append(boundary
						+ "\r\nContent-Disposition: form-data; name=\"incomplete\"\r\n\r\n1\r\n");
			}
		}
		sb.append(boundary);
		sb.append("\r\nContent-Disposition: form-data; name=\"filecontent\"; filename=\""
				+ FName + "\"\r\n");
		sb.append("Content-Type: multipart/form-data\r\nContent-Transfer-Encoding: binary\r\n\r\n");
		return sb.toString();
	}

	private void sendFile(OutputStream os, long start, int nbyte)
			throws FileNotFoundException, IOException {
		RandomAccessFile raf = new RandomAccessFile(file, "r");
		FileInputStream fis = new FileInputStream(file);
		byte[] buffer = new byte[4096];
		int bytesRead = 0;// Read File into memStream.
		int bytesSended = 0;
		int koliknacist = 4096;
		if (nbyte < 4096) {
			koliknacist = nbyte;
		}
		raf.seek(start);
		while (raf.getFilePointer() < start + nbyte && bytesRead != -1) {
			bytesRead = raf.read(buffer, 0, koliknacist);

			os.write(buffer, 0, bytesRead);
			os.flush();
			bytesSended += bytesRead;
			if (nbyte - bytesSended < 4096) {
				koliknacist = nbyte - bytesSended;
			}
			uploadedSize += bytesRead;
			System.out.println(bytesRead + "Posilam: " + buffer + " Poslano: "
					+ uploadedSize + " START pozice: " + start + " nbyte: "
					+ nbyte);
		}
		fis.close();
	}

	private boolean checkUpload(String response) throws FileNotFoundException,
			IOException {
		String[] s = response.split("\n");

		// premiumAccountID = Utils.parseLastValueStr(s[0], "=");
		fileURL = getID(Utils.parseLastValueStr(s[1], "="));
		// if (fileURL != null) fileID = Integer.parseInt(fileURL);
		fileKillURL = Utils.parseLastValueStr(s[2], "=");
		// if (fileKillURL != null) killCode = Integer.parseInt(fileKillURL);
		System.out
				.println("Kill code: " + fileKillURL + " ,File id:" + fileURL);
		long fileLength = Long.parseLong(Utils.parseLastValueStr(s[3], "="));
		String MD5 = Utils.parseLastValueStr(s[4], "=");

		if (fileLength == file.length()
				&& MD5.equalsIgnoreCase(Utils.getMD5(file))) {
			return true;
		}

		return false;
	}

	public FileInfo getFileInfo() throws ServiceProviderException {
		// TODO Auto-generated method stub
		return null;
	}

	private String getFileKillCode(String s) {
		int i = s.lastIndexOf('=');
		System.out.println("INDEX: " + i);
		String fid = s.substring(i);
		return fid;
	}

	private String getID(String s) {
		int i = s.lastIndexOf('/');
		String fid = s.substring(i - 9, i);
		return fid;
	}
}
